<template>
  <div
    v-if="!initializing"
    class="vc-component"
    :style="visual.parseStyle(currNode.currStyle)"
    @click="() => eventHandler.trigger('点击事件')"
  >
    <div
      v-if="readonly || (cropper && imageUrl)"
      :class="['image-box', border ? 'border' : '']"
      :style="cropper ? 'cursor: pointer' : ''"
    >
      <el-image
        v-if="imageUrl !== ''"
        preview-teleported
        hide-on-click-modal
        :fit="fit"
        :src="imageUrl"
        :preview-src-list="!preview || cropper ? [] : [imageUrl]"
        :style="{
          width: width || '100%',
          height: height || '100%',
          maxWidth: '100%',
          maxHeight: '100%'
        }"
        @click="showCropper()"
      />
      <cc-icon
        v-if="!readonly"
        size="14"
        color="red"
        iconId="018dc9c3efd3a0502886"
        title="删除"
        @click.stop="deleteImage"
      />
    </div>
    <div v-else class="image-edit-box">
      <el-upload
        class="vc-image" action=""
        :http-request = "handleUpload"
        :show-file-list="false"
        :accept="'image/*'"
        :before-upload="handleBeforeUpload"
      >
        <cc-icon v-if="loading" size="30" color="#999" iconId="018dcab3d3dfd6e82393" class="spinner" />
        <span v-else-if="imageUrl && !loading" class="image-item">
          <cc-icon size="14" color="red" iconId="018dc9c3efd3a0502886" title="删除" @click.stop="deleteImage" />
          <img :src="imageUrl" alt />
        </span>
        <cc-icon v-else size="30" color="#999" iconId="018dca3b4707c4c43a2f" />
      </el-upload>
    </div>

    <el-dialog
      v-model="dialogVisible"
      width="900px"
      append-to-body
      destroy-on-close
      draggable
      class="cc-page-comp-dialog"
      :close-on-click-modal="false"
    >
      <template #header>
        <div class="header">
          <div class="title">图片裁剪</div>
        </div>
      </template>
      <div class="dialog-box">
        <div style="width: 400px;height: 400px">
          <VueCropper
            ref="cropperRef"
            style="width:100%"
            :img="imageUrl"
            :output-size="option.size"
            :output-type="option.outputType"
            :info="false"
            :full="option.full"
            :fixed="option.fixed"
            :fixed-number="option.fixedNumber"
            :can-move="option.canMove"
            :can-move-box="option.canMoveBox"
            :fixed-box="option.fixedBox"
            :original="option.original"
            :auto-crop="option.autoCrop"
            :auto-crop-width="option.autoCropWidth"
            :auto-crop-height="option.autoCropHeight"
            :center-box="option.centerBox"
            :high="option.high"
            :max-img-size="option.max"
            @realTime="realTime"
          ></VueCropper>
          <div style="padding-top: 20px;height: 40px;">
            <el-button
              type="primary"
              @click="changeScale(1)"
            ><cc-icon iconId="018ece4f6c751e36f773"/></el-button>
            <el-button
              type="primary"
              @click="changeScale(-1)"
            ><cc-icon iconId="018ece4f7296e9555472"/></el-button>
            <el-button
              type="primary"
              @click="rotateLeft()"
            ><cc-icon iconId="018ece4f6c4954d8f1d5"/></el-button>
            <el-button
              type="primary"
              @click="rotateRight()"
            ><cc-icon iconId="018ece4f6dc8c9e76788"/></el-button>
          </div>
        </div>
        <div class="preview-box" style="height: 450px;">
          <div class="preview-img">
            <div
              :style="{
                'width': previewData.w + 'px',
                'height': previewData.h + 'px',
                'overflow': 'hidden'
              }"
            >
              <div :style="previewData.div">
                <img :src="previewData.url" :style="previewData.img"  alt="" />
              </div>
            </div>
          </div>
          <div style="padding-top: 20px;height: 40px;">
            <div>预览</div>
          </div>
        </div>
      </div>
      <template #footer>
        <el-button
          size="default"
          type="info"
          @click="dialogVisible = false"
        >取消</el-button>
        <el-button
          size="default"
          type="primary"
          @click="() => submitDialog()"
          :loading="dialogLoading"
        >提交</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, inject, getCurrentInstance, onUnmounted } from 'vue'
import api from "@/http/api";
import visual from "@/visual/js/visual";
import EventHandler from "@/visual/js/event";
import { ElMessage, ElMessageBox } from "element-plus";
import { VueCropper } from 'vue-cropper';
import 'vue-cropper/dist/index.css';

const props = defineProps({
  node: Object,
  inputParam: Object
});
const initializing = ref(true);
const currNode = ref(props.node);
const eventHandler = new EventHandler(
  inject('eventHandler', Function, true),
  getCurrentInstance(),
  currNode.value
);

const loading = ref(true);
const fileId = ref('');
const imageUrl = ref('');
const cropperRef = ref();
const cropper = ref(false);
const cropperStyle = ref('');
const cropperWidth = ref(160);
const cropperHeight = ref(90);
const readonly = ref(false);
const border = ref(false);
const preview = ref(false);
const previewData = ref({});
const fit = ref('');
const width = ref('');
const height = ref('');

const dialogVisible = ref(false);
const dialogLoading = ref(false);
const option = ref({
  size: 1,
  full: false,
  outputType: 'png',
  canMove: true,
  original: false,
  canMoveBox: true,
  autoCrop: true,
  autoCropWidth: 200,
  autoCropHeight: 150,
  centerBox: false,
  high: true,
  max: 2000,
  show: true,
  fixed: true,
  fixedBox: true,
  mode: '100% auto',
  fixedNumber: [200, 150]
});

const handleUpload = (data) => {
  return new Promise((resolve, reject) => {
    api.upload({'file': data.file, type: data.file.type}).then((res) => {
      loading.value = false;
      fileId.value = res.data.id;
      imageUrl.value = URL.createObjectURL(data.file);
      resolve();
    }).catch(() => {
      loading.value = false;
      reject();
    });
  });
};

const handleBeforeUpload = (file) => {
  if (loading.value) {
    ElMessage.error("图片正在上传中，请稍候再试！");
    return false;
  }
  loading.value = true;

  let isImage = file.type.includes("image");
  if (!isImage) {
    loading.value = false;
    ElMessage.error("上传文件类型必须是图片!");
  }
  let isLt2M = file.size / 1024 / 1024 < 2;
  if (!isLt2M) {
    loading.value = false;
    ElMessage.error("上传图片大小不能超过 2MB!");
  }
  return isImage && isLt2M;
};

const deleteImage = () => {
  fileId.value = '';
  imageUrl.value = '';
};

const showCropper = () => {
  if (cropper.value) {
    dialogVisible.value = true;
  }
};

const realTime = (data) => {
  previewData.value = data;
};

const submitDialog = () => {
  ElMessageBox.confirm('请确认是否提交裁剪后的图片？', '提示', {type: 'warning'}).then(() => {
    cropperRef.value.getCropBlob((file) => {
      api.upload({'fileId': fileId.value, 'file': file, type: 'image/png'}).then((res) => {
        dialogLoading.value = false;
        fileId.value = res.data.id;
        imageUrl.value = URL.createObjectURL(file);
        ElMessage.success("图片上传成功！");
        dialogVisible.value = false;
      }).catch((e) => {
        ElMessage.success("图片上传失败：" + e.message);
        dialogLoading.value = false;
      });
    });
  }).catch(() => {});
};

const changeScale = (num) => {
  num = num || 1;
  cropperRef.value.changeScale(num);
};

const rotateLeft = () => {
  cropperRef.value.rotateLeft()
};

const rotateRight = () => {
  cropperRef.value.rotateRight ()
};

const init = async(styleId) => {
  initializing.value = true;
  visual.initStyle(currNode.value, styleId);
  readonly.value = currNode.value.currCompStyle['readonly'] || false;
  fit.value = currNode.value.currCompStyle['fit'];
  width.value = currNode.value.currCompStyle['width'];
  height.value = currNode.value.currCompStyle['height'];
  border.value = currNode.value.currCompStyle['border'] || false;
  preview.value = currNode.value.currCompStyle['preview'] || false;
  cropper.value = currNode.value.currCompStyle['cropper'] || false;
  if (cropper.value) {
    cropperWidth.value = currNode.value.currCompStyle['cropper.width'] || 160;
    cropperHeight.value = currNode.value.currCompStyle['cropper.height'] || 90;
    option.value.autoCropWidth = cropperWidth.value;
    option.value.autoCropHeight = cropperHeight.value;
    option.value.fixedNumber = [cropperWidth.value, cropperHeight.value];
    cropperStyle.value = `width: ${cropperWidth.value * 2}px;height:${cropperHeight.value * 2}px`;
  }
  await refresh();
  await nextTick(() => initializing.value = false);
};

const loadValue = async() => {
  const dataList = (await visual.loadData(
    currNode.value.compData,
    eventHandler,
    getData(),
    currNode.value)).data || [];
  fileId.value = dataList.length > 0 && dataList[0]['内容'] || '';
  imageUrl.value = fileId.value ? import.meta.env.VITE_IMAGE_PATH + fileId.value : '';
  loading.value = false;
};

const getData = () => {
  return {
    inputParam: Object.assign({}, currNode.value.inputParam, props.inputParam),
    value: fileId.value
  };
};

const changeStyle = (styleId) => {
  init(styleId);
};

const refresh = async() => {
  initializing.value = true;
  await loadValue();
  await nextTick(() => initializing.value = false);
};

onMounted(async() => {
  await init();
  await loadValue();
  await eventHandler.trigger('初始化事件');
});

onUnmounted(() => {
  eventHandler.unregister();
});

defineExpose({ getData, changeStyle, refresh });
</script>

<style scoped>
.vc-component {
  width: inherit;
  height: inherit;
}
.vc-image {
  height: 100%;
  width: 100%;
  flex: 1;
  justify-content: center;
  align-items: center;
  display: flex;
  border: 1px dashed #c2c2c2;
}

.vc-image :deep(.el-upload) {
  display: flex;
  text-align: center;
  cursor: pointer;
  outline: 0;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

.vc-image :deep(.el-upload span) {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.vc-image:not(.is-disabled) :deep(.el-upload) {
  cursor: pointer;
}

.vc-image:not(.is-disabled) :deep(.el-upload:hover) {
  border-color: #409EFF;
}

.loading-icon {
  font-size: 28px;
  color: #8c939d;
  position: absolute;
}

.plus-icon {
  font-size: 28px;
  color: #8c939d;
  position: absolute;
}

.vc-image img {
  max-width: 100%;
  max-height: 100%;
}
.image-edit-box {
  width: inherit;
  height: inherit;
}
.image-box {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  position: relative;
}
.border {
  border: 1px dashed #c2c2c2;
}
.image-box img {
  max-width: 100%;
  max-height: 100%;
}
.vc-image :deep(.el-upload:after) {
  display: block;
  margin-top: 100%;
  content: ""
}
.image-item {
  position: relative;
}
.image-box .vc-icon, .image-item .vc-icon {
  position: absolute;
  top: 5px;
  right: 5px;
}
.dialog-box {
  height: 450px;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}
.preview-box {
  height: 100%;
  width: 45%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.preview-img {
  border: 2px dotted #cccccc;
}
</style>